/**
 * Copyright 2008 Adam Ruggles.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package kiff.interceptor;

import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import kiff.entity.User;
import kiff.service.UserService;
import kiff.util.SessionConstants;

import org.apache.commons.lang.StringUtils;
import org.apache.struts2.StrutsStatics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Inject;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
/**
 * Login Interceptor.
 * @author Adam
 * @version $Id$
 * 
 * Created on Nov 3, 2008 at 9:58:37 PM 
 */
public class LoginInterceptor implements Interceptor, StrutsStatics  {
	/**
	 * Serial Version UID.
	 */
	private static final long serialVersionUID = -1512953358877453339L;

	/**
     * The <code>Logger</code> is used by the application to generate a log messages.
     */
    private final Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);

	/**
	 * The request parameter that represents a login attempt.
	 */
	public static final String ATTEMPT = "attempt";

	/**
	 * The request parameter that represents a login password.
	 */
	public static final String PASSWORD = "password";

	/**
	 * The request parameter that represents a login username.
	 */
	public static final String USERNAME = "username";

	/**
	 * The User Service, contains the business logic for validating the user.
	 */
	private UserService userService;

	/**
	 * {@inheritDoc}
	 * @see com.opensymphony.xwork2.interceptor.Interceptor#destroy()
	 */
	public void destroy() { }

	/**
	 * Returns the value of the named text.
	 * @param text The name of text to be found.
	 * @return The value of the named text.
	 */
	private String getText(final String text, final Locale locale) {
        return LocalizedTextUtil.findText(getClass(), text, locale);
    }

	/**
	 * {@inheritDoc}
	 * @see com.opensymphony.xwork2.interceptor.Interceptor#init()
	 */
	public void init() { }

	/**
	 * {@inheritDoc}
	 * @see com.opensymphony.xwork2.interceptor.Interceptor#intercept(com.opensymphony.xwork2.ActionInvocation)
	 */
	public String intercept(final ActionInvocation actionInvocation) throws Exception {
		logger.debug("Verifiying that the user is logged in");
		final ActionContext context = actionInvocation.getInvocationContext();
		Action action = (Action) actionInvocation.getAction();
		HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST);
	    HttpSession session =  request.getSession(true);
	    User user = (User) session.getAttribute(SessionConstants.USER_SESSION);
	    if (user == null) {
	    	// User is not logged in.
	    	logger.debug("URL=[{}] QS=[{}]", request.getRequestURL().toString(), request.getQueryString());
	    	String attempt = request.getParameter(ATTEMPT);
	    	String username = request.getParameter(USERNAME);
    		String password = request.getParameter(PASSWORD);
    		logger.debug("Checking attempt value of [{}]", attempt);
    		// Check for a login attempt.
	    	if (!StringUtils.isBlank(attempt)) {
	    		// Validate the username and password then attempt to validate the user's credentials.
	    		Locale locale = context.getLocale();
	    		if (StringUtils.isBlank(username)) {
	    			logger.debug("Username is empty");
	    			if (action instanceof ValidationAware) {
	    				((ValidationAware) action).addFieldError(USERNAME, getText("validation.username", locale));
	    			}
	    		} else if (StringUtils.isBlank(password)) {
	    			logger.debug("Password is empty");
	    			if (action instanceof ValidationAware) {
	    				((ValidationAware) action).addFieldError(PASSWORD, getText("validation.password", locale));
	    			}
	    		} else {
	    			logger.debug("Validating [{}]", username);
	    			user = userService.validate(username, password);
	    			if (user != null) {
	    				logger.debug("Validation successful");
	    				// User has been successfully validated, put the user into the session.
	    				session.setAttribute(SessionConstants.USER_SESSION, user);
	    				// Invoke secured action.
	    				return actionInvocation.invoke();
	    			}
	    			logger.debug("Validation failed");
	    			if (action instanceof ValidationAware) {
	    				((ValidationAware) action).addFieldError(USERNAME,
	    						getText("validation.invalidCredentials", locale));
	    			}
	    		}
	    	}
	    	// User is not logged in redirect the user to the login page.
	    	return Action.LOGIN;
	    }
	    if (action instanceof UserAware) {
			((UserAware) action).setUser(user);
		}
	    // User is logged in - invoke secured action.
	    return actionInvocation.invoke();
	}

	/**
	 * Sets userService.
	 * @param userService the userService to set.
	 */
	@Inject
	public void setUserService(final UserService userService) {
		this.userService = userService;
	}

}
